package vip.aster.workflow.controller;

import cn.hutool.core.io.IoUtil;
import jakarta.servlet.http.HttpServletResponse;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import io.swagger.v3.oas.annotations.Operation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.engine.*;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.springframework.web.bind.annotation.*;
import vip.aster.common.exception.BusinessException;
import vip.aster.common.utils.PageInfo;
import vip.aster.common.utils.ResultInfo;
import vip.aster.framework.log.annotation.Log;
import vip.aster.framework.log.enums.BusinessTypeEnum;
import vip.aster.framework.security.entity.SecurityUser;
import vip.aster.workflow.query.InstanceQuery;
import vip.aster.workflow.service.DataSourceService;
import vip.aster.workflow.service.ProcessService;
import vip.aster.workflow.vo.SubmitFormVO;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 流程控制层
 *
 * @author Aster
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/workflow/process")
public class WfProcessController {

    /**
     * 流程service
     */
    private ProcessService processService;

    /**
     * 数据源service
     */
    private DataSourceService dataSourceService;


    private ProcessEngine processEngine;


    private TaskService taskService;


    private RepositoryService repositoryService;


    private RuntimeService runtimeService;

    /**
     * 提交表单
     *
     * @param submitFormVO 表单数据
     * @return 提交结果
     */
    @PostMapping("/submit")
    public ResultInfo<String> submit(@RequestBody SubmitFormVO submitFormVO) {
        processService.submit(submitFormVO);
        return ResultInfo.success();
    }

    /**
     * 分页查询
     *
     * @param query 查询条件
     * @return 分页数据
     */
    @PostMapping("/selectPage")
    public ResultInfo<PageInfo<Map<String, Object>>> selectPage(@RequestBody Map<String, Object> query) {
        PageInfo<Map<String, Object>> pageInfo = dataSourceService.selectPage(query);
        return ResultInfo.success(pageInfo);
    }

    /**
     * 查询任务
     *
     * @return 任务数据
     */
    @PostMapping("/taskPage")
    public ResultInfo<PageInfo<Map<String, Object>>> taskPage(@RequestBody Map<String, Object> query) {
        List<Task> taskList = taskService.createTaskQuery()
                .taskAssignee(SecurityUser.getUserId())
                .list();
//        log.info("待办集合：{}", JSONArray.from(taskList));
        PageInfo<Map<String, Object>> pageInfo = processService.selectTask(query);
        return ResultInfo.success(pageInfo);
    }

    @PostMapping("/completeTask/{taskId}")
    public ResultInfo<String> completeTask(@PathVariable String taskId, @RequestBody Map<String, Object> formData) {
        taskService.complete(taskId);
        return ResultInfo.success();
    }


    @GetMapping("/showPic/{taskId}")
    public void showPic(HttpServletResponse response, @PathVariable String taskId) {
        OutputStream out = null;
        try {
            out = response.getOutputStream();
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            List<Execution> executions = runtimeService
                    .createExecutionQuery()
                    .processInstanceId(task.getProcessInstanceId())
                    .list();
            //得到正在执行的Activity的Id
            List<String> activityIds = new ArrayList<>();
            List<String> flows = new ArrayList<>();
            for (Execution exe : executions) {
                List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
                activityIds.addAll(ids);
            }
            BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
            ProcessEngineConfiguration config = processEngine.getProcessEngineConfiguration();
            ProcessDiagramGenerator diagramGenerator = config.getProcessDiagramGenerator();
            InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows, config.getActivityFontName(), config.getLabelFontName(), config.getAnnotationFontName(), config.getClassLoader(), 2.0, true);
            IoUtil.write(out, true, IoUtil.readBytes(in));
        } catch (Exception e) {
            log.error("【读取流程图片失败, 系统异常】", e);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    @PostMapping("/instance/completed")
    @Operation(summary = "获取所有已审批通过的流程实例")
    @Log(type = BusinessTypeEnum.SEARCH)
    public ResultInfo<List<JSONObject>> getCompletedInstances(@RequestBody InstanceQuery queryParams) {
        String formCode = queryParams.getCode();
        if (StrUtil.isBlank(formCode)) {
            throw new BusinessException("表单编码不能为空！");
        }
        List<JSONObject> list = processService.selectCompletedInstances(formCode);
        return ResultInfo.success(list);
    }

    @PostMapping("/instance/page")
    @Operation(summary = "流程实例分页查询")
    @Log(type = BusinessTypeEnum.SEARCH)
    public ResultInfo<PageInfo<JSONObject>> instancePageList(@RequestBody InstanceQuery instanceQuery) {
        PageInfo<JSONObject> pageInfo = processService.selectInstancePageByCode(instanceQuery.getCode(), instanceQuery);
        return ResultInfo.success(pageInfo);
    }

}
